package ar.edu.itba.infovis.TPF;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jackson.map.ObjectMapper;
import org.joda.time.DateTime;

import ar.edu.itba.infovis.TPF.twitter.Tweet;
import ar.edu.itba.infovis.TPF.twitter.TweetStat;
import ar.edu.itba.infovis.TPF.twitter.TweetStats;
import ar.edu.itba.infovis.TPF.twitter.TwitterStream;

import com.google.common.collect.Lists;

public class MainVizServlet extends HttpServlet {

	private static final long serialVersionUID = 1485575476511861134L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		int minFollowers = 0;
		int updateFreq = 0;
		int groupingFreq = 0;
		
		resp.setContentType("application/json");
		
		String minFollowersAux = req.getParameter("minFollowers");
		String groupingFreqAux = req.getParameter("groupingFreq");
		String updateFreqAux = req.getParameter("updateFreq");
		
		try{
			minFollowers = Integer.valueOf(minFollowersAux);
			groupingFreq = Integer.valueOf(groupingFreqAux);
			updateFreq = Integer.valueOf(updateFreqAux);
		} catch (NumberFormatException e){
			resp.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
			return;
		}
		
		if( minFollowers < 0 || groupingFreq <= 0){
			resp.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
			return;
		}
		
		TwitterStream stream = TwitterStream.getInstance();
		List<String> keywords = stream.getKeywords();
		List<TweetStats> twitterData = new ArrayList<TweetStats>();
		DateTime firstTweet = DateTime.now();
		
		for(String k: keywords){
			SortedSet<Tweet> tws = stream.getTweets(k);
			if( tws == null ){
				resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
				return;
			}
			
			if( !tws.isEmpty() && firstTweet.compareTo(tws.last().getCreated_at()) > 0){
				firstTweet = tws.last().getCreated_at();
			}
		}
		
		DateTime now = DateTime.now().minus(DateTime.now().getMillis() % (groupingFreq * 1000));
		
		for(String k : keywords) {
			SortedSet<Tweet> tweets = stream.getTweets(k);
			SortedSet<TweetStat> stats = new TreeSet<TweetStat>();
			for(int total = 0; total<updateFreq ;total+=groupingFreq) {
				DateTime begining = now.minusSeconds(total + groupingFreq);
				DateTime end = now.minusMillis(total*1000 + 1);
				if(begining.isBefore(firstTweet)) {
					break;
				}
				stats.add(filterTweets(tweets, begining, end, minFollowers));
			}
			twitterData.add(new TweetStats(k, stats));
		}

		ObjectMapper mapper = new ObjectMapper();
		PrintWriter writer = resp.getWriter();
		
		writer.write("{");
		Iterator<TweetStats> it = twitterData.iterator();
		while(it.hasNext()){
			TweetStats ts = it.next();
			writer.write("\""+ts.getKeyword() + "\": ");
			writer.write(mapper.writeValueAsString(ts.getStats()));
			if( it.hasNext() ){
				writer.write(", ");
			}
		}
		writer.write("}");
	}
	
	private TweetStat filterTweets(SortedSet<Tweet> tweets, DateTime start, DateTime end, int minFollowers){
		int tweetCount = 0;
		int visibility = 0;
		int amount = 0;
		int retweetAmount = 0;
		int replysAmount = 0;
		List<String> sampleTexts = Lists.newArrayList();
		SortedSet<Tweet> sortedByFollowers = new TreeSet<Tweet>(new TweetsByFollowersComparator());
		
		for(Tweet t: tweets) {
			if( t.getCreated_at().isAfter(start.minusMillis(1)) && t.getCreated_at().isBefore(end) 
					&& (t.getUser() == null || t.getUser().getFollowers_count() >= minFollowers)){
				visibility += t.getUser().getFollowers_count();
				++tweetCount;
				sortedByFollowers.add(t);
				if(t.getRetweet_count()>0) {
					++retweetAmount;
				}
				if(t.getIn_reply_to_screen_name()!=null) {
					++replysAmount;
				}
			}
		}
		
		for(Tweet t: sortedByFollowers) {
			if(t.getCreated_at().isAfter(start)) {
				sampleTexts.add(t.getText());
				++amount;
				if(amount>=5) {
					break;
				}
			}
		}
		
		return new TweetStat(tweetCount, end, sampleTexts, visibility, retweetAmount, replysAmount);
	}
}
